package com.cater.generate.util;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;

import com.cater.generate.entity.ColumnClass;

import freemarker.template.Template;

/**
 * @Description: TODO
 * @author: yong
 * @time:2018年4月25日 下午10:54:23
 */
public class CodeGenerateUtils {
	private final String AUTHOR = "yong";//作者
	private final String CURRENT_DATE = "2019/04/27";//生成日期【】
	private final String tableName = "project_collection_record";//表名【】
	private final String packageName = "com.cater.project";//包名【】
	private final String tableAnnotation = "收款记录";//对类的描述说明
	private final String URL = "jdbc:mysql://127.0.0.1:3306/hunter_dev";//数据库连接
	private final String USER = "root";//数据库名
	private final String PASSWORD = "123456";//数据库密码
	private final String DRIVER = "com.mysql.jdbc.Driver";//数据库驱动
	private final String diskPath = "D://temp//";//生成类的存放路径
	private final String viewPath = "project";//页面访问路径
	private final String changeTableName = replaceUnderLineAndUpperCase(tableName);//转换表名
	//private final String accessPath = replaceUnderLineAndendCase(tableName);//请求路径
	private final String accessPath = "collectionRecord";//请求路径

	public Connection getConnection() throws Exception {
		Class.forName(DRIVER);
		Connection connection = DriverManager.getConnection(URL, USER, PASSWORD);
		return connection;
	}

	public static void main(String[] args) throws Exception {
		CodeGenerateUtils codeGenerateUtils = new CodeGenerateUtils();
		codeGenerateUtils.generate();
	}

	public void generate() throws Exception {
		try {
			File file =  new File(diskPath);
			if(!file.exists()) {
				file.mkdirs();
			}
			Connection connection = getConnection();
			DatabaseMetaData databaseMetaData = connection.getMetaData();
			ResultSet resultSet = databaseMetaData.getColumns(null, "%", tableName, "%");
			// 生成Model文件
			generateModelFile(resultSet);
			// 生成Dao文件
			generateDaoFile(resultSet);
			// 生成Mapper文件
			generateMapperFile(resultSet);
			// 生成服务实现层文件
			generateServiceImplFile(resultSet);
			// 生成Controller层文件
			generateControllerFile(resultSet);
			// 生成web页面文件
			generateHtmljsp(resultSet);
			// 生成服务层接口文件
			// generateServiceInterfaceFile(resultSet);
			// 生成DTO文件
			// generateDTOFile(resultSet);
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {

		}
	}

	private void generateModelFile(ResultSet resultSet) throws Exception {

		final String suffix = ".java";
		final String path = diskPath + changeTableName + suffix;
		final String templateName = "Entity.ftl";
		File mapperFile = new File(path);
		List<ColumnClass> columnClassList = new ArrayList<ColumnClass>();
		ColumnClass columnClass = null;
		while (resultSet.next()) {
			columnClass = new ColumnClass();
			if (resultSet.getString("COLUMN_NAME").equals("delflag"))
				continue;
			if (resultSet.getString("COLUMN_NAME").equals("createDate"))
				continue;
			if (resultSet.getString("COLUMN_NAME").equals("createUserId"))
				continue;
			if (resultSet.getString("COLUMN_NAME").equals("updateDate"))
				continue;
			if (resultSet.getString("COLUMN_NAME").equals("updateUserId"))
				continue;
			// 获取字段名称
			columnClass.setColumnName(resultSet.getString("COLUMN_NAME"));
			// 获取字段类型
			columnClass.setColumnType(resultSet.getString("TYPE_NAME"));
			// 转换字段名称，如 sys_name 变成 sysName
			columnClass.setChangeColumnName(replaceUnderLineAndendCase(resultSet.getString("COLUMN_NAME")));
			// 字段在数据库的注释
			columnClass.setColumnComment(resultSet.getString("REMARKS"));
			// 转换字段名称，如 sys_name 变成 SysName
			columnClass.setCapitalColumnName(replaceUnderLineAndUpperCase(resultSet.getString("COLUMN_NAME")));
			columnClassList.add(columnClass);
		}
		Map<String, Object> dataMap = new HashMap<String, Object>();
		dataMap.put("model_column", columnClassList);
		generateFileByTemplate(templateName, mapperFile, dataMap);

	}

	private void generateDTOFile(ResultSet resultSet) throws Exception {
		final String suffix = "DTO.java";
		final String path = "D://" + changeTableName + suffix;
		final String templateName = "DTO.ftl";
		File mapperFile = new File(path);
		Map<String, Object> dataMap = new HashMap<String, Object>();
		generateFileByTemplate(templateName, mapperFile, dataMap);
	}

	private void generateControllerFile(ResultSet resultSet) throws Exception {
		final String suffix = "Controller.java";
		final String path = diskPath + changeTableName + suffix;
		final String templateName = "Controller.ftl";
		File mapperFile = new File(path);
		Map<String, Object> dataMap = new HashMap<String, Object>();
		dataMap.put("view_path", viewPath);
		generateFileByTemplate(templateName, mapperFile, dataMap);
	}

	private void generateServiceImplFile(ResultSet resultSet) throws Exception {
		final String suffix = "ServiceImpl.java";
		final String path = diskPath + changeTableName + suffix;
		final String templateName = "ServiceImpl.ftl";
		File mapperFile = new File(path);
		Map<String, Object> dataMap = new HashMap<String, Object>();
		generateFileByTemplate(templateName, mapperFile, dataMap);
	}

	private void generateServiceInterfaceFile(ResultSet resultSet) throws Exception {
		final String prefix = "I";
		final String suffix = "Service.java";
		final String path = diskPath + prefix + changeTableName + suffix;
		final String templateName = "ServiceInterface.ftl";
		File mapperFile = new File(path);
		Map<String, Object> dataMap = new HashMap<String, Object>();
		generateFileByTemplate(templateName, mapperFile, dataMap);
	}

	private void generateRepositoryFile(ResultSet resultSet) throws Exception {
		final String suffix = "Repository.java";
		final String path = diskPath + changeTableName + suffix;
		final String templateName = "Repository.ftl";
		File mapperFile = new File(path);
		Map<String, Object> dataMap = new HashMap<String, Object>();
		generateFileByTemplate(templateName, mapperFile, dataMap);
	}

	private void generateDaoFile(ResultSet resultSet) throws Exception {
		final String suffix = "Dao.java";
		final String path = diskPath + changeTableName + suffix;
		final String templateName = "Dao.ftl";
		File mapperFile = new File(path);
		Map<String, Object> dataMap = new HashMap<String, Object>();
		generateFileByTemplate(templateName, mapperFile, dataMap);

	}

	private void generateMapperFile(ResultSet resultSet) throws Exception {
		final String suffix = "Mapper.xml";
		final String path = diskPath + changeTableName + suffix;
		final String templateName = "Mapper.ftl";
		File mapperFile = new File(path);
		List<ColumnClass> columnClassList = new ArrayList<ColumnClass>();
		ColumnClass columnClass = null;
		Connection connection = getConnection();
		DatabaseMetaData databaseMetaData = connection.getMetaData();
		resultSet = databaseMetaData.getColumns(null, "%", tableName, "%");
		while (resultSet.next()) {
			// id字段略过
			if (resultSet.getString("COLUMN_NAME").equals("id"))
				continue;
			if (resultSet.getString("COLUMN_NAME").equals("delflag"))
				continue;
			if (resultSet.getString("COLUMN_NAME").equals("createDate"))
				continue;
			if (resultSet.getString("COLUMN_NAME").equals("createUserId"))
				continue;
			if (resultSet.getString("COLUMN_NAME").equals("updateDate"))
				continue;
			if (resultSet.getString("COLUMN_NAME").equals("updateUserId"))
				continue;
			columnClass = new ColumnClass();
			// 获取字段名称
			columnClass.setColumnName(resultSet.getString("COLUMN_NAME"));
			// 获取字段类型
			columnClass.setColumnType(resultSet.getString("TYPE_NAME"));
			// 转换字段名称，如 sys_name 变成 sysName
			columnClass.setChangeColumnName(replaceUnderLineAndendCase(resultSet.getString("COLUMN_NAME")));
			columnClass.setInupColumnName("#{" + replaceUnderLineAndendCase(resultSet.getString("COLUMN_NAME")) + "}");
			// 字段在数据库的注释
			columnClass.setColumnComment(resultSet.getString("REMARKS"));
			columnClassList.add(columnClass);
		}
		Map<String, Object> dataMap = new HashMap<String, Object>();
		dataMap.put("model_column", columnClassList);
		generateFileByTemplate(templateName, mapperFile, dataMap);

	}

	private void generateHtmljsp(ResultSet resultSet) throws Exception {
		final String[] suffixgroup = {"list.jsp","add.jsp","update.jsp","detail.jsp"};
		final String[] templategroup = {"list.ftl","add.ftl","update.ftl","detail.ftl"};
		int i=0;
		for (String temp : suffixgroup) {
			final String suffix = temp;
			final String path = diskPath + changeTableName + suffix;
			final String templateName = templategroup[i];
			File mapperFile = new File(path);
			List<ColumnClass> columnClassList = new ArrayList<ColumnClass>();
			ColumnClass columnClass = null;
			Connection connection = getConnection();
			DatabaseMetaData databaseMetaData = connection.getMetaData();
			resultSet = databaseMetaData.getColumns(null, "%", tableName, "%");
			while (resultSet.next()) {
				// id字段略过
				if (resultSet.getString("COLUMN_NAME").equals("id"))
					continue;
				if (resultSet.getString("COLUMN_NAME").equals("delflag"))
					continue;
				if (resultSet.getString("COLUMN_NAME").equals("createDate"))
					continue;
				if (resultSet.getString("COLUMN_NAME").equals("createUserId"))
					continue;
				if (resultSet.getString("COLUMN_NAME").equals("updateDate"))
					continue;
				if (resultSet.getString("COLUMN_NAME").equals("updateUserId"))
					continue;
				columnClass = new ColumnClass();
				// 获取字段名称
				columnClass.setColumnName(resultSet.getString("COLUMN_NAME"));
				// 获取字段类型
				columnClass.setColumnType(resultSet.getString("TYPE_NAME"));
				// 转换字段名称，如 sys_name 变成 sysName
				columnClass.setChangeColumnName(replaceUnderLineAndendCase(resultSet.getString("COLUMN_NAME")));
				columnClass.setInupColumnName("#{" + replaceUnderLineAndendCase(resultSet.getString("COLUMN_NAME")) + "}");
				// 字段在数据库的注释
				columnClass.setColumnComment(resultSet.getString("REMARKS"));
				columnClassList.add(columnClass);
			}
			Map<String, Object> dataMap = new HashMap<String, Object>();
			dataMap.put("model_column", columnClassList);
			generateFileByTemplate(templateName, mapperFile, dataMap);
			i++;
		}
	}

	private void generateFileByTemplate(final String templateName, File file, Map<String, Object> dataMap)
			throws Exception {
		Template template = FreeMarkerTemplateUtils.getTemplate(templateName);
		FileOutputStream fos = new FileOutputStream(file);
		dataMap.put("table_name_small", tableName);
		dataMap.put("table_name", changeTableName);
		dataMap.put("access_path", accessPath);
		dataMap.put("author", AUTHOR);
		dataMap.put("date", CURRENT_DATE);
		dataMap.put("package_name", packageName);
		dataMap.put("table_annotation", tableAnnotation);
		Writer out = new BufferedWriter(new OutputStreamWriter(fos, "utf-8"), 10240);
		template.process(dataMap, out);
	}

	public String replaceUnderLineAndUpperCase(String str) {
		StringBuffer sb = new StringBuffer();
		sb.append(str);
		int count = sb.indexOf("_");
		while (count != 0) {
			int num = sb.indexOf("_", count);
			count = num + 1;
			if (num != -1) {
				char ss = sb.charAt(count);
				char ia = (char) (ss - 32);
				sb.replace(count, count + 1, ia + "");
			}
		}
		String result = sb.toString().replaceAll("_", "");
		return StringUtils.capitalize(result);
	}

	public String replaceUnderLineAndendCase(String str) {
		StringBuffer sb = new StringBuffer();
		sb.append(str);
		int count = sb.indexOf("_");
		while (count != 0) {
			int num = sb.indexOf("_", count);
			count = num + 1;
			if (num != -1) {
				char ss = sb.charAt(count);
				char ia = (char) (ss - 32);
				sb.replace(count, count + 1, ia + "");
			}
		}
		String result = sb.toString().replaceAll("_", "");
		return result;
	}
}
